﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http.Filters;

namespace suirui.ZhuMu.WebCore
{
    /// <summary>
    /// 压缩返回信息
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class CompressionAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            var content = actionExecutedContext.Response.Content;
            var acceptEncoding = actionExecutedContext.Request.Headers.AcceptEncoding.
                Where(x => x.Value == "gzip" || x.Value == "deflate").ToList();
            if (acceptEncoding.Count() > 0 && content != null && actionExecutedContext.Request.Method != HttpMethod.Options)
            {
                var first = acceptEncoding.FirstOrDefault();
                if (first != null)
                {
                    var bytes = content.ReadAsByteArrayAsync().Result;
                    switch (first.Value)
                    {
                        case "gzip":
                            actionExecutedContext.Response.Content = new ByteArrayContent(CompressionHelper.GZipBytes(bytes));
                            actionExecutedContext.Response.Content.Headers.Add("Content-Encoding", "gzip");
                            break;
                        case "deflate":
                            actionExecutedContext.Response.Content = new ByteArrayContent(CompressionHelper.DeflateBytes(bytes));
                            actionExecutedContext.Response.Content.Headers.Add("Content-encoding", "deflate");
                            break;
                    }
                }
            }
            base.OnActionExecuted(actionExecutedContext);
        }
    }
    /// <summary>
    /// 压缩帮助类
    /// </summary>
    internal static class CompressionHelper
    {
        public static byte[] DeflateBytes(byte[] bytes)
        {
            if (bytes.Length <= 0)
            {
                return null;
            }
            using (var output = new MemoryStream())
            {
                using (var compressor = new Ionic.Zlib.DeflateStream(output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.Default))
                {
                    compressor.Write(bytes, 0, bytes.Length);
                }
                return output.ToArray();
            }
        }

        public static byte[] GZipBytes(byte[] bytes)
        {
            if (bytes.Length <= 0)
            {
                return null;
            }
            using (var output = new MemoryStream())
            {
                using (var compressor = new Ionic.Zlib.GZipStream(output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.Default))
                {
                    compressor.Write(bytes, 0, bytes.Length);
                }
                return output.ToArray();
            }
        }
    }
}
